#include "ManejadorArchivos.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 128

/* ******************************************************************
 *                DEFINICION DE LOS TIPOS DE DATOS                  *
 * *****************************************************************/

struct _ManejadorArchivos {
    FILE* archivo;
    char* nombreArchivo;
    char* nombreArchivoSinExt; // sin su extensión
    bool terminoDeLeer;
};

/* *****************************************************************
 *                 			FUNCIONES AUXILIARES				   *
 * *****************************************************************/

char* extraer_nombre (char* ruta) {
	int largo = strlen (ruta);
	
	int i = largo - 1;
	while ( i >= 0 ) {
		if ( ruta[i] == '/' ) break;
		i--;
	}
	int largoNombre = ( largo - i );
	i++;
	
	char* nombre = malloc ( sizeof(char) * (largoNombre + 1) );
	if (!nombre) return NULL;
	
	for ( int j = 0 ; j < largoNombre ; j++ ) {
		nombre[j] = ruta[j+i];
	}
	nombre[largoNombre] = '\0';
	return nombre;
}


/* *****************************************************************
 *                 PRIMITIVAS DEL ManejadorArchivos				   *
 * *****************************************************************/

// Crea un ManejadorArchivos.
// Post: devuelve un ManejadorArchivos o NULL en caso de error.
ManejadorArchivos_t* ManejadorArchivos_crear(char* ruta) {
  	if (!ruta) return NULL;
  	char* nombreDelArchivo = extraer_nombre (ruta);
  	
  	if (!nombreDelArchivo) return NULL;
  	int largoNombre = strlen(nombreDelArchivo);
  	
  	ManejadorArchivos_t* ManejadorArchivos = malloc(sizeof(ManejadorArchivos_t));
	if(ManejadorArchivos == NULL) return NULL;
	
	//ManejadorArchivos->nombreArchivo = nombreDelArchivo;
	ManejadorArchivos->nombreArchivo = ruta;
	
	/* Se guarda el nombre sin la extensión */
	ManejadorArchivos->nombreArchivoSinExt = malloc((largoNombre - 3)*sizeof(char) );
	if (ManejadorArchivos->nombreArchivoSinExt == NULL) return NULL;
	strncpy(ManejadorArchivos->nombreArchivoSinExt, nombreDelArchivo, largoNombre - 4);
	ManejadorArchivos->nombreArchivoSinExt[largoNombre - 4] = '\0';
	ManejadorArchivos->archivo = fopen(ManejadorArchivos->nombreArchivo,"r");
	if (!(ManejadorArchivos->archivo)) return NULL;
	
	free (nombreDelArchivo);
	ManejadorArchivos->terminoDeLeer=false;
	return ManejadorArchivos;
}

// Devuelve el nombre del archivo con el cual se está trabajando o NULL
// en caso de error.
char* ManejadorArchivos_nombreDelArchivo(ManejadorArchivos_t* ManejadorArchivos) {
	if (!ManejadorArchivos) return NULL;
	return ( ManejadorArchivos->nombreArchivo );
}

// Devuelve el nombre del archivo con el cual se está trabajando pero 
// sin extensión, o NULL en caso de error.
char* ManejadorArchivos_nombreDelArchivoSinExt(ManejadorArchivos_t* ManejadorArchivos) {
	if (!ManejadorArchivos) return NULL;
	return ( ManejadorArchivos->nombreArchivoSinExt );
}

// Lee el archivo hasta el '\n' o fin del mismo. Devuelve NULL en caso
// de error.
char* ManejadorArchivos_leer(ManejadorArchivos_t* ManejadorArchivos){
	if (!ManejadorArchivos) return NULL;
	
	size_t tam = BUFSIZE; 
    char* buffer = malloc(tam * sizeof(char));
    
    if (!buffer) return NULL;

    // Lee hasta el enter o hasta el fin de archivo
    size_t i = 0;
    int c = fgetc(ManejadorArchivos->archivo);
    while ( c != '\n' && c != EOF ) {
    
        buffer[i] = c;  

        if (i+1 >= tam) { 
            tam *= 2;
            char* aux = realloc(buffer, tam * sizeof(char));
            if (!aux) break;
            buffer = aux;
        }
		
        c = fgetc(ManejadorArchivos->archivo);
        i++;
    }
	
	if(c==EOF) ManejadorArchivos->terminoDeLeer=true;
	
	// Si el string está vacío, devuelve NULL
	/*if (i == 0) {
		free(buffer);
		return NULL;
	}*/

	// Terminador de cadenas
    buffer[i] = '\0';

    /* Reduce la memoria pedida al minimo. */
    char* aux = realloc(buffer, (i+1) * sizeof(char));
    if (!aux) return buffer;
    return aux;
}

// Devuelve true si terminó de leer el archivo y false en cualquier otro caso.
bool ManejadorArchivos_terminoDeLeer(ManejadorArchivos_t* ManejadorArchivos) {
	if (!ManejadorArchivos) return false;
	return ( ManejadorArchivos->terminoDeLeer );
}

// Destruye el ManejadorArchivos, cierra el archivo.
void ManejadorArchivos_destruir(ManejadorArchivos_t *ManejadorArchivos) {
	if (!ManejadorArchivos) return;
	if (ManejadorArchivos->archivo) fclose(ManejadorArchivos->archivo);
	if (ManejadorArchivos->nombreArchivo) free(ManejadorArchivos->nombreArchivo);
	if (ManejadorArchivos->nombreArchivoSinExt) free(ManejadorArchivos->nombreArchivoSinExt);
	free(ManejadorArchivos);
}
